import { Flex, Card, Tag, Input, InputRef } from "antd"
import { useEffect, useImperativeHandle, useRef, useState } from "react"
import { PlusOutlined } from "@ant-design/icons"
import './index.css'

type CellProps = {
  color: string,
  children: React.ReactNode
}

type CellListProps = {
  lessons: string[],
  domRef: any,
  setLessons: (lessons: string[]) => void
}

const tagPlusStyle: React.CSSProperties = {
  height: 50,
  lineHeight: 3.6,
  borderStyle: 'dashed',
}
const tagInputStyle: React.CSSProperties = {
  width: 100,
  height: 50,
  marginInlineEnd: 8,
  verticalAlign: 'top',
};

const colors = [
  'darkblue',
  'purple',
  'darkred',
  'darkcyan',
  'tomato',
  'darkorchid',
  'slategrey',
  'slateblue',
  'magenta',
  'deeppink',
  'yellowgreen',
  'limegreen',
  'tan',
  'gold',
  'orange',
  'green',
  'blue',
]

const _lessons = [
  '语文',
  '数学',
  '英语',
  '物理',
  '化学',
  '生物',
  '政治',
  '历史',
  '地理',
  '体育',
  '音乐',
  '美术',
]

const Cell = ({ color, children }: CellProps) => {
  const cellStyle = {
    backgroundColor: color,
  }
  return (
    <div className="draggableItem" draggable style={cellStyle}>
      <span>{children}</span>
    </div>
  )
}

const CellList = ({ lessons, domRef, setLessons }: CellListProps) => {
  const cellRef = useRef(null)
  useImperativeHandle(domRef, () => cellRef.current, [cellRef])
  const getColor = (i: number) => colors[i % colors.length]

  // 编辑课程
  const [editInputValue, setEditInputValue] = useState('')
  const [editInputIndex, setEditInputIndex] = useState(-1)
  const editInputRef = useRef<InputRef>(null)
  useEffect(() => {
    editInputRef.current?.focus()
  }, [editInputValue])
  const handleEditInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    setEditInputValue(e.target.value)
  };
  const handleEditInputConfirm = () => {
    const newLessons = [...lessons]
    newLessons[editInputIndex] = editInputValue
    setLessons(newLessons.filter(Boolean))
    setEditInputIndex(-1)
    setEditInputValue('')
  }
  const onDoubleClick = (e: React.MouseEvent, lesson: string, index: number) => {
    e.preventDefault()
    setEditInputIndex(index)
    setEditInputValue(lesson)
  }
  return (
    <div className="cellList" ref={cellRef}>
      {lessons.map((lesson, index) => {
        if (editInputIndex === index) {
          return (
            <Input
              ref={editInputRef}
              key={index}
              style={tagInputStyle}
              value={editInputValue}
              onChange={handleEditInputChange}
              onBlur={handleEditInputConfirm}
              onPressEnter={handleEditInputConfirm}
            />
          )
        }
        return (
          <Cell
            key={index}
            color={getColor(index)}
          >
            <span onDoubleClick={e => onDoubleClick(e, lesson, index)}>{lesson}</span>
          </Cell>
        )
      })}
    </div>
  )
}

const LessonsTable = ({ domRef }: any) => {
  const tableRef = useRef(null)
  useImperativeHandle(domRef, () => tableRef.current, [tableRef])
  return (
    <table border={1} ref={tableRef}>
      <thead>
        <tr>
          <th>时</th>
          <th>一</th>
          <th>二</th>
          <th>三</th>
          <th>四</th>
          <th>五</th>
          <th>六</th>
          <th>日</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td></td>
          <td></td>
          <td></td>
          <td></td>
          <td></td>
          <td></td>
          <td></td>
          <td></td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td></td>
          <td></td>
          <td></td>
          <td></td>
          <td></td>
          <td></td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td></td>
          <td></td>
          <td></td>
          <td></td>
          <td></td>
          <td></td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td></td>
          <td></td>
          <td></td>
          <td></td>
          <td></td>
          <td></td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td></td>
          <td></td>
          <td></td>
          <td></td>
          <td></td>
          <td></td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td></td>
          <td></td>
          <td></td>
          <td></td>
          <td></td>
          <td></td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td></td>
          <td></td>
          <td></td>
          <td></td>
          <td></td>
          <td></td>
        </tr>
      </tbody>
    </table>
  )
}

const TimeTable = () => {
  const [lessons, setLessons] = useState(_lessons)
  const timeTableRef = useRef<HTMLDivElement>(null)
  const leftRef = useRef<HTMLDivElement>(null)
  const rightRef = useRef<HTMLDivElement>(null)

  // 新增课程
  const [inputVisible, setInputVisible] = useState(false)
  const [inputValue, setInputValue] = useState('')
  const showInput = () => {
    setInputVisible(true);
  }
  const inputRef = useRef<InputRef>(null)
  useEffect(() => {
    if (inputVisible) {
      inputRef.current?.focus()
    }
  }, [inputVisible])
  const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    setInputValue(e.target.value);
  }
  const handleInputConfirm = (isBlur = true) => {
    if (inputValue && !lessons.includes(inputValue)) {
      setLessons([...lessons, inputValue])
    }
    isBlur && setInputVisible(false)
    setInputValue('')
  }

  // 拖拽监听
  useEffect(() => {
    let sourceEle: HTMLElement | null = null
    let targetEle: HTMLElement | null = null

    // 记录拖动的目标
    const handleDragStart = (e: DragEvent) => {
      const ele = e.target as HTMLElement
      if (!ele.draggable) return
      if (leftRef.current?.contains(ele)) {
        e.dataTransfer!.effectAllowed = 'copy'
      }
      if (rightRef.current?.contains(ele)) {
        e.dataTransfer!.effectAllowed = 'move'
      }
      sourceEle = ele
    }
    // 经过的元素允许放置
    const handleDragOver = (e: DragEvent) => {
      e.preventDefault()
    }
    // 记录放置的目标容器
    const handleDrop = (e: DragEvent) => {
      targetEle = e.target as HTMLElement
    }
    // 判断目标放置处理
    const handleDragEnd = (e: DragEvent) => {
      e.preventDefault()
      e.stopImmediatePropagation()
      // console.log('dragend')
      // console.log('target', e.target)
      // console.log('sourceEle', sourceEle)
      // console.log('targetEle', targetEle)
      const isCopy = e.dataTransfer!.effectAllowed === 'copy'
      const isMove = e.dataTransfer!.effectAllowed === 'move'
      const isDropRightZone = rightRef.current?.contains(targetEle)
      if (isCopy) {
        if (!isDropRightZone) return
        const cloneEle = sourceEle!.cloneNode(true)
        targetEle!.appendChild(cloneEle)
        return
      }
      if (isMove) {
        if (isDropRightZone) {
          const cloneEle = sourceEle!.cloneNode(true)
          targetEle!.appendChild(cloneEle)
        }
        sourceEle?.parentNode?.removeChild(sourceEle)
      }
    }

    timeTableRef.current?.addEventListener('dragstart', handleDragStart)
    timeTableRef.current?.addEventListener('dragover', handleDragOver)
    timeTableRef.current?.addEventListener('drop', handleDrop)
    timeTableRef.current?.addEventListener('dragend', handleDragEnd)
    return () => {
      timeTableRef.current?.removeEventListener('dragstart', handleDragStart)
      timeTableRef.current?.removeEventListener('dragover', handleDragOver)
      timeTableRef.current?.removeEventListener('drop', handleDrop)
      timeTableRef.current?.removeEventListener('dragend', handleDragEnd)
    }
  }, [])
  return (
    <Flex
      gap="small"
      justify="space-between"
      style={{ height: '100%' }}
      ref={timeTableRef}
    >
      <Card style={{ width: '22%' }} hoverable>
        <div style={{ marginBottom: '10px' }}>
          <Tag color="black">尝试下拖拽API</Tag>
          <Tag color="deeppink">双击文本编辑</Tag>
        </div>
        <CellList lessons={lessons} setLessons={setLessons} domRef={leftRef} />
        {
          inputVisible ? (
            <Input
              ref={inputRef}
              type="text"
              style={tagInputStyle}
              value={inputValue}
              onChange={handleInputChange}
              onBlur={() => handleInputConfirm()}
              onPressEnter={() => handleInputConfirm(false)}
            />
          ) : (
            <Tag
              style={tagPlusStyle}
              icon={<PlusOutlined />}
              onClick={showInput}
            >
              New Lesson
            </Tag>
          )
        }
      </Card>
      <Card style={{ flex: 1 }} hoverable>
        <LessonsTable domRef={rightRef} />
      </Card>
    </Flex>
  )
}

export default TimeTable
